/*
 * Copyright 2012-2013 EZC Group S.A. RCS Luxembourg B140949
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.yobidrive.y3.utils;

import java.security.MessageDigest;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

public class CryptoUtils {
	
	static private final Logger logger = Logger.getLogger(CryptoUtils.class);

	public static String getHMAC(String keyStr, String data) throws Exception{
		byte[] keyBytes = keyStr.getBytes("UTF-8") ;
		SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");
		Mac m = Mac.getInstance("HmacSHA1");
		m.init(key);
		m.update(data.getBytes("UTF-8"));
		byte[] mac = m.doFinal();
		return toHexString(mac) ;
	}
	
	public static String getB64HMAC(String keyStr, String data) {
		try {
			byte[] keyBytes = keyStr.getBytes("UTF-8") ;
			SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA1");
			Mac m = Mac.getInstance("HmacSHA1");
			m.init(key);
			m.update(data.getBytes("UTF-8"));
			byte[] mac = m.doFinal();
			return new String(Base64.encodeBase64(mac),"UTF-8");
		} catch ( Throwable th ) {
			logger.error("Unable to compute HMAC",th);
			return null ;
		}
	}
	
	public static String hash(String source) throws Exception{
		String encoded = "";
		MessageDigest md = null;
		md = MessageDigest.getInstance("SHA-1");
		md.update(source.getBytes("UTF-8")) ;
		byte[] v = md.digest() ;
		encoded = toHexString(v) ;
		return encoded ;
	}
	
	public static String hash(byte[] source) {
    	String encoded = "";
    	MessageDigest md = null;
    	try {
    		md = MessageDigest.getInstance("SHA-1");
    		md.update(source) ;
    		byte[] v = md.digest() ;
    		encoded = toHexString(v) ;
    	} catch (Throwable th) {
    		logger.error("Unable to compute hash",th);
    	} finally{
    		md.reset();
    	}
    	return encoded ;
	}
	
	private static final String HEX_DIGITS = "0123456789abcdef";
	private static String toHexString(byte[] v) {
        StringBuffer sb = new StringBuffer(v.length * 2);
        for (int i = 0; i < v.length; i++) {
            int b = v[i] & 0xFF;
             sb.append(HEX_DIGITS.charAt(b >>> 4))
               .append(HEX_DIGITS.charAt(b & 0xF));
        }
        return sb.toString();
    }
	
	public static SecretKey getForStringSecretKey(String base64EncodedKey) {
		if ( base64EncodedKey == null || "".equals(base64EncodedKey) ) {
			return null ;
		}
		byte[] decoded = Base64.decodeBase64(base64EncodedKey);
		return new SecretKeySpec(decoded,"AES") ;
	}
	
	public static String decryptSecretFromB64AndIVWithAESKey(String secretEncoded, SecretKey aesKey) {
	    try {
	      int idxAt = secretEncoded.indexOf('@') ;
	      if ( idxAt < 0 ) {
	    	  return null ;
	      }
	      byte[] iv = Base64.decodeBase64(secretEncoded.substring(0, idxAt)) ;
		  IvParameterSpec ips = new IvParameterSpec(iv);
	      byte[] data = Base64.decodeBase64(secretEncoded.substring(idxAt+1)) ;
	      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	      cipher.init(Cipher.DECRYPT_MODE, aesKey, ips);
	      byte[] cipherData = cipher.doFinal(data);
	      return new String(cipherData,"UTF-8") ;
	    }
	    catch (Throwable th) {
	    	logger.error("Unable to decrypt secret",th);
	    } 
	    return null;
	}
}
